package cw.spring.security.acl.poc.dao;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * Abstract base class for Hibernate DAOs.
 * 
 * @param <T>
 *          the entity type
 */
public abstract class BaseDAOHibernateImpl<T> extends HibernateDaoSupport implements IBaseDAO<T> {

  /**
   * The class related to this DAO.
   */
  protected Class<T> entityClass;
  private static final Logger log = LoggerFactory.getLogger(BaseDAOHibernateImpl.class);

  public BaseDAOHibernateImpl(Class<T> entityClass) {
    this.entityClass = entityClass;
  }

  @Override
  protected void initDao() throws Exception {
    super.initDao();
    /*
     * We do not want the hibernateTemplate to create new sessions since it can lead to connection leaks : a session may be created without the
     * transaction interceptor being notified and the connection being released into the connection pool.
     */
    this.getHibernateTemplate().setAllowCreate(false);
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#findAll()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#findAll()
   */
  @SuppressWarnings("unchecked")
  public Set<T> findAll() {
    Criteria criteria = getSession().createCriteria(entityClass);
    criteria.setCacheable(true);
    List<T> objectsFound = criteria.list();
    return new HashSet<T>(objectsFound);
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#findAll()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#findAll(int)
   */
  @SuppressWarnings("unchecked")
  public Set<T> findAll(int maxReturnedEntities) {
    // 1. we try to retrieve more objects than the limit
    Criteria criteria = getSession().createCriteria(entityClass);
    criteria.setCacheable(true);
    if (maxReturnedEntities != 0) {
      criteria.setMaxResults(maxReturnedEntities + 1);
    }
    List<T> objectsFound = criteria.list();
    // 2. we check that the number of retrieved objects doesn't exceed the limit
    return new HashSet<T>(objectsFound);
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#findByPrimaryKey()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#findById(long)
   */
  @SuppressWarnings("unchecked")
  public T findById(final long pk) {
    return (T) getSession().get(entityClass, pk);
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#create()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#create(T)
   */
  public T create(final T t) {
    getSession().save(t);
    return t;
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#create()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#saveOrUpdate(T)
   */
  public T saveOrUpdate(final T t) {
    getSession().saveOrUpdate(t);
    return t;
  }

  /*
   * (non-Javadoc)
   * 
   * @see north.stardust2.dao.BaseDAO#update(north.stardust2.model.PersistentObject)
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#update(T)
   */
  public void update(final T t) {
    getSession().update(t);
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.foo.bar.dao.BaseDAO#delete()
   */
  /*
   * (non-Javadoc)
   * 
   * @see cw.spring.security.acl.poc.dao.IBaseDAO#delete(T)
   */
  public void delete(final T t) {
    getSession().delete(t);
  }

}
